﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Mvc;

using Mvc.XForms.Controls.Settings;
using Mvc.XForms.Utilities;
using System.Web;

namespace Mvc.XForms.Controls {
	public class XFormGroup<TParentContext, TContext> : XFormContextBase<TParentContext, TContext>, IGroup<TContext> {
		private Expression<Func<TParentContext, TContext>> bind;

		public GroupSettings<TContext> Settings { get; private set; }
		public Action<IGroup<TContext>> TemplateAction { get; set;}
		public string Template { get; set; }
		public string Tag { get; set; }

		public override XFormControlType ControlType {
			get { return XFormControlType.Group; }
		}

		public XFormGroup(IContainerControl<TParentContext> parent, Expression<Func<TParentContext, TContext>> bind)
			: base(parent, bind.Body) {
			this.bind = bind;
			ModelContext = bind.Compile()(parent.ModelContext);
			if (ModelContext == null)
				ModelContext = Activator.CreateInstance<TContext>();

			Settings = new GroupSettings<TContext>(this);
			CssClass.Add("group");
		}

		public override void Render() {
			ApplySettingsOrDefaults();

			var resp = XForm.HttpContext.Response;
			OutputGroup(resp);
		}

		public virtual void ApplySettingsOrDefaults() {
			Label = Label ?? bind.Body.ExtractMember().CapitalizeSpace();
			Tag = Tag ?? "div";
		}

		public virtual void OutputGroup(HttpResponseBase resp) {
			var groupBegin = XForm.Formatter.GroupBegin(this);
			var groupEnd = XForm.Formatter.GroupEnd(this);

			resp.Write(groupBegin);
			TemplateAction(this);
			resp.Write(groupEnd);
		}

		public override object ToJson() {
			if (IsInRepeatTemplate) {
				var json = new {
					id = ID,
					type = (int)ControlType,
					acts = Actions.Select(act => act.ToJson()),
					cons = Controls.Select(con => con.ToJson()).Where(obj => obj != null)
				};
				return json;
			}

			return null;
		}
	}
}